/**
 * @file dev.h
 * @brief Architecture Device Interfaces
 *
 * This module abstracts the common interface to the
 * devices on chip referred as the architecture
 * devices
 *
 * @author yemt@witsi.cn
 * @date 2011-08-02
 * @version rxSys.dev.02
 */
#ifndef DEV_H_
#define DEV_H_

#include <stdint.h>
#include <sys/types.h>

/**
 * Computes the element numbers in the array x
 */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

#define K       1024            /**< Kilo- */
#define M       (1024 * K)      /**< Mega- */
#define G       (1024 * M)      /**< Giga- */

/************************************************************************
 * IRQ: Interrupt Request Interface
 ************************************************************************/
typedef void (*irq_handler_t)(void);                        /**< IRQ Handler Type */
typedef int32_t irq_no_t;                                   /**< IRQ Number Type */
int request_irq(irq_no_t irq_num, irq_handler_t routine);   /**< Request and Enable a IRQ */
void irq_disable(irq_no_t irq_num);                         /**< Disable a IRQ */
void irq_enable(irq_no_t irq_num);                          /**< Enable a IRQ */

/************************************************************************
 * Hardware Timer Interface
 ************************************************************************/
typedef void (*timer_irq_t)(void);                          /**< Timer Interrupt Handler Type */
typedef enum {
        TIMER_PERIODIC,
        TIMER_ONESHOT,
        TIMER_FREERUN,
}timer_mode_t;
void timer_hw_init(int n, timer_mode_t mod, uint32_t clock,
                uint32_t reload, timer_irq_t handler);      /**< Setup a Timer */
void timer_hw_start(int n);                                 /**< Start a Timer */
void timer_hw_stop(int n);                                  /**< Stop a Timer */
uint32_t timer_hw_value(int n);                             /**< Return the Current Value of a Timer */
int timer_hw_flag(int n);                                   /**< Return the Overflow Flag of a Timer */
void timer_hw_flag_clear(int n);                            /**< Clear the Overflow Flag of a Timer */
void timer_hw_set_load(int n, uint32_t load);               /**< Set the Load Value of a Timer */
void timer_hw_set_reload(int n, uint32_t reload);           /**< Set the Re-load Value of a Timer */

void watchdog_enable(uint32_t value);                       /**< Watchdog Timer Enable */
void pwm_init(int n, uint32_t clock, uint32_t duty);
void pwm_start(int n);
void pwm_stop(int n);

/************************************************************************
 * Hardware Timer Interface
 ************************************************************************/
void set_rtc_seconds(uint32_t val);                         /**< Set the RTC Seconds */
uint32_t get_rtc_seconds(void);                             /**< Get the RTC Seconds */
void rtc_enable(void);                                      /**< Enable the RTC, called once */
/************************************************************************
 * BUS: SPI Interface
 ************************************************************************/
/**
 * SPI Slave
 */
typedef struct {
        /**
         * priv and cs will be used by drivers,
         * so do not modify them outside
         */
        uint32_t priv;                 /**< private data used by spi bus drivers, maybe a pointer */
        void (*ctl_cs)(uint32_t);      /**< cs, may use gpio */
        uint8_t bus;                   /**< SPI BUS Number from 0 */
        uint8_t sub_id;                /**< Sub-device indexed from 0 */
}spi_slave_t;

/**
 * SPI Parameters
 */
typedef struct {
        uint32_t baud;          /**< Clock Baud Rate */
        uint8_t bus_16bit;      /**< Data Size, 16 bit (1) or 8 bit (0) */
        uint8_t cpha;           /**< Clock Phase, (0 or 1)*/
        uint8_t cpol;           /**< Clock Polarity, (0 or 1) */
        uint8_t lsb_mod;        /**< MSB First(0) or LSB first(1)*/
}spi_param_t;

#define SPI_XFER_BEGIN  0x01    /* Assert CS before Transferring */
#define SPI_XFER_END    0x02    /* Deassert CS after Transferring */

int spi_register_slave(spi_slave_t *, spi_param_t *);   /**< Register a Slave to the Bus */
int spi_xfer(spi_slave_t * spi, const void *dout,
                int len, void *din, uint32_t flags);    /**< Issue a Transferring to the Slave */

/************************************************************************
 * GPIO: General Purpose IO Interface
 ************************************************************************/
typedef void (*gpio_irq_t)(void);       /**< GPIO Interrupt Handler Type */

/*
 * Interrupt Trigger Type
 */
typedef enum {
        GPIO_INT_LOW = 0,               /**< Low Level Trigger */
        GPIO_INT_HIGH,                  /**< High Level Trigger */
        GPIO_INT_FALLING,               /**< Falling Edge Trigger */
        GPIO_INT_RISING,                /**< Rising Edge Trigger */
        GPIO_INT_FALLING_RISING         /**< Both Falling and Rising Edges Trigger */
}gpio_int_type_t;

void gpio_set_output(uint32_t gpio_num, uint32_t attr);         /**< Set GPIO to Output IO */
void gpio_set_input(uint32_t gpio_num, uint32_t attr);          /**< Set GPIO to Input IO */
int gpio_input(uint32_t gpio_num);                              /**< Get GPIO Input Value */
void gpio_output(uint32_t gpio_num, int val);                   /**< Set GPIO Output Value */
void gpio_irq_enable(uint32_t gpio_num);                        /**< Enable GPIO Interrupt */
void gpio_irq_disable(uint32_t gpio_num);                       /**< Disable GPIO Interrupt */
void gpio_request_irq(uint32_t gpio_num,
                gpio_int_type_t type, gpio_irq_t handler);      /**< Request GPIO Interrupt */

/************************************************************************
 * Device Security Information
 ************************************************************************/
void read_dev_id(uint8_t * buf);
void read_vendor_pk(uint8_t * buf);
void buzzer_start(void);
void buzzer_stop(void);

#endif /* DEV_H_ */
